/**
 * 
 */
package physics;

import javax.measure.quantity.Quantity;
import javax.measure.unit.Unit;

import org.jscience.mathematics.vector.Vector;
import org.jscience.physics.amount.Amount;

/**
 * @author Flavio
 *
 */
public class FourVector<Q extends Quantity, T extends Transform<T>> extends Vector<Amount<?>>{
	
	private Amount<?>[] coord;
	
	public FourVector(double coord_0, double coord_1, double coord_2, double coord_3, Unit<Q> unit) {
		coord = new Amount<?>[4];
		coord[0] = Amount.valueOf(coord_0, unit);
		coord[1] = Amount.valueOf(coord_1, unit);
		coord[2] = Amount.valueOf(coord_2, unit);
		coord[3] = Amount.valueOf(coord_3, unit);
	}
	
	public FourVector(Amount<?> coord_0, Amount<?> coord_1, Amount<?> coord_2, Amount<?> coord_3) {
		coord = new Amount<?>[4];
		coord[0] = coord_0;
		coord[1] = coord_1;
		coord[2] = coord_2;
		coord[3] = coord_3;
	}

	public void setCoordinates(double coord_0, double coord_1, double coord_2, double coord_3, Unit<Q> unit) {
		coord[0] = Amount.valueOf(coord_0, unit);
		coord[1] = Amount.valueOf(coord_1, unit);
		coord[2] = Amount.valueOf(coord_2, unit);
		coord[3] = Amount.valueOf(coord_3, unit);
	}
	
	public FourVector(FourVector<Q, T> toCopy) {
		coord = new Amount<?>[4];
		coord[0] = toCopy.get(0);
		coord[1] = toCopy.get(1);
		coord[2] = toCopy.get(2);
		coord[3] = toCopy.get(3);
	}

	@Override
	public Vector<Amount<?>> copy() {
		return new FourVector<>(this.get(0), this.get(1), this.get(2), this.get(3));
	}

	@Override
	public Amount<?> get(int i) {
		if( i < 0 || i > 3 ) throw new IndexOutOfBoundsException();
		return this.coord[i];
	}

	@Override
	public int getDimension() {
		return 4;
	}

	@Override
	public Vector<Amount<?>> opposite() {
		return new FourVector<>(this.coord[0].opposite(), this.coord[1].opposite(), 
								this.coord[2].opposite(), this.coord[3].opposite());
	}

	@Override
	public Vector<Amount<?>> plus(Vector<Amount<?>> toAdd) {
		if( !( toAdd instanceof FourVector<?,?> ) ) throw new UnsupportedOperationException();
		Amount<?> coord_0 = this.get(0).plus(toAdd.get(0));
		Amount<?> coord_1 = this.get(1).plus(toAdd.get(1));
		Amount<?> coord_2 = this.get(2).plus(toAdd.get(2));
		Amount<?> coord_3 = this.get(3).plus(toAdd.get(3));
		return new FourVector<>(coord_0, coord_1, coord_2, coord_3);
	}

	@Override
	public Vector<Amount<?>> times(Amount<?> k) {
		Amount<?> coord_0 = this.get(0).times(k);
		Amount<?> coord_1 = this.get(1).times(k);
		Amount<?> coord_2 = this.get(2).times(k);
		Amount<?> coord_3 = this.get(3).times(k);
		return new FourVector<>(coord_0, coord_1, coord_2, coord_3);
	}

	@Override
	public Amount<?> times(Vector<Amount<?>> toDotMultiply) {
		if( !( toDotMultiply instanceof FourVector<?,?> ) ) throw new UnsupportedOperationException();
		Amount<?> x_0y_0 = this.get(0).times(toDotMultiply.get(0));
		Amount<?> x_1y_1 = this.get(1).times(toDotMultiply.get(1));
		Amount<?> x_2y_2 = this.get(2).times(toDotMultiply.get(2));
		Amount<?> x_3y_3 = this.get(3).times(toDotMultiply.get(3));
		return x_0y_0.minus(x_1y_1).minus(x_2y_2).minus(x_3y_3);
	}
	
	public FourVector<?,T> getCoordinates(Frame<T> referenceFrame) {
		return referenceFrame.fromBaseReferenceFrameToThis.transform(this);
	}

}
